package 题目集.倍增算法.lca;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.List;

/**
 * https://www.luogu.com.cn/problem/P10391 文言文翻译： 给你一棵树，树上每个点有个权值。
 * 问从a点到b点的路径中，权值的种类
 * 思路： 一眼lca,ci很小<=20，开20个到根节点的种类数量，维护差分信息。
 */
public class ch08_维护树上点权种类 {
	static int maxn = (int) (1e5 + 10), maxc = 21;

	static int n, q;
	static int[] val = new int[maxn];
	static int[] deep = new int[maxn];
	static int[][] st = new int[maxn][maxc];
	static int[][] fa = new int[maxn][(int) Math.ceil(Math.log(maxn) / Math.log(2))];
	static int power;
	static List<Integer>[] tree = new List[maxn];

	public static void main(String[] args) {
		Reader2 sc = new Reader2();
		n = sc.nextInt();
		q = sc.nextInt();
		for (int i = 1; i <= n; i++) {
			tree[i] = new ArrayList<>();
			val[i] = sc.nextInt();
		}
		for (int i = 1; i < n; i++) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			tree[u].add(v);
			tree[v].add(u);
		}
		build();
		for (int i = 1; i <= q; i++) {
			int a = sc.nextInt();
			int b = sc.nextInt();
			int ans = query(a, b);
			System.out.println(ans);
		}
	}

	private static void build() {
		power = (int) Math.ceil(Math.log(n) / Math.log(2));
		level(1);
		for (int p = 1; p < power; p++) {
			for (int i = 1; i <= n; i++) {
				fa[i][p] = fa[fa[i][p - 1]][p - 1];
			}
		}
	}

	private static void level(int root) {
		int[] q = new int[maxn];
		int h = 0, t = 0;
		q[t++] = root;
		st[root][val[root]]++;
		fa[root][0] = root;
		while (h < t) {
			int u = q[h++];
			for (int v : tree[u]) {
				if (v != fa[u][0]) {
					q[t++] = v;
					fa[v][0] = u;
					deep[v] = deep[u] + 1;
					st[v] = st[u].clone();
					st[v][val[v]]++;
				}
			}
		}
	}

	public static int query(int a, int b) {
		int p = lca(a, b);
		// 差分需要多减一格
		p = p == 1 ? 0 : fa[p][0];
		int ans = 0;
		for (int i = 1; i < maxc; i++) {
			int cnt = st[a][i] + st[b][i] - 2 * st[p][i];
			if (cnt > 0) {
				ans++;
			}
		}
		return ans;
	}

	public static int lca(int a, int b) {
		int high = deep[a] < deep[b] ? a : b;
		int low = deep[a] >= deep[b] ? a : b;
		for (int p = power - 1; p >= 0; p--) {
			if (deep[fa[low][p]] >= deep[high]) {
				low = fa[low][p];
			}
		}
		if (low == high) {
			return low;
		}
		for (int p = power - 1; p >= 0; p--) {
			if (fa[low][p] != fa[high][p]) {
				low = fa[low][p];
				high = fa[high][p];
			}
		}
		return fa[low][0];
	}

	static class Reader2 {
		static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

		public Reader2(Object... o) {
		}

		public int nextInt() {
			try {
				in.nextToken();
			} catch (Exception ignored) {
			}
			return (int) in.nval;
		}
	}

}
